#include <FL/Fl.H>
#include <FL/Fl_Gl_Window.H>
#include <FL/Fl_Choice.H>
#include <FL/Fl_Button.H>
#include <FL/gl.h>
#include <math.h>
#include <vector> 
#include <cassert>
#include <fstream>


#include "Waveform.h"


class GlWindow : public Fl_Gl_Window { 
  Waveform* mWfm; //pointer to the waveform - shared with the parent class.
  
  void draw() {
    printf("width: %d, height: %d\n", w(), h());
    if (!valid()) {
      valid(1);
      glMatrixMode (GL_PROJECTION);
      glLoadIdentity ();
      glOrtho (0, w(), -h()/2, h()/2, 0, 1);
      glMatrixMode (GL_MODELVIEW);
      glDisable(GL_DEPTH_TEST);
    }
    glClear(GL_COLOR_BUFFER_BIT);
    glColor3f(1.0, 1.0, 1.0);
    
    //white line across the center of the screen.
    glBegin(GL_LINE);
    glVertex2f(0, 0);
    glVertex2f(w(), 0);
    glEnd();
  }
  
  int handle( int event ) {
    switch ( event ) {
    default:
      return Fl_Gl_Window::handle(event);
    }
  }

  void resize(int X,int Y,int W,int H) {
    // not sure if this code is correct since I put height on +/-h()/2
    Fl_Gl_Window::resize(X,Y,W,H);
    glMatrixMode (GL_PROJECTION);
    glLoadIdentity ();
    glViewport(0,0,W,H);
    glOrtho (0, W, -H/2, H/2, 0, 1);
    glMatrixMode (GL_MODELVIEW);
    glDisable(GL_DEPTH_TEST);
    printf("resizing!\n");
    redraw();
  }

public:
  
  ~GlWindow( void ) {
    invalidate();
    hide();
  }
  
  GlWindow(int X,int Y,int W,int H,Waveform* wfm) : Fl_Gl_Window(X,Y,W,H) {
    end();
    mWfm = wfm;
  }

};


class GuiWindow : public Fl_Window {
  //segmentation fault definitly caused by fl_gl_window, but I can't locate the root of the problem
  GlWindow* gwin;
  Fl_Choice* mFsChoice;
  Fl_Choice* mTChoice;
  Fl_Button* mPlayButton;
  Fl_Button* mStopButton;
  Fl_Button* mResetButton;
  
  Fl_Choice* mWaveformChoice;
  Fl_Choice* mWaveformFsChoice;
  Fl_Button* mWaveformInsertButton;
  
  Waveform* mWfm;
  
  // could have a single button callback, and pass a button specifying enum value
  
  
  // PlayButton
  void playButton(void) {
    printf("Play Button Pressed!\n");
  }
  
  static void playButton(Fl_Widget* w, void*userdata) {
    GuiWindow* win = (GuiWindow*)userdata;
    win->playButton();
  }
  
  // StopButton
  void stopButton(void) {
    printf("Stop Button Pressed!\n");
  }
  
  static void stopButton(Fl_Widget* w, void*userdata) {
    GuiWindow* win = (GuiWindow*)userdata;
    win->stopButton();
  }

  // ResetButton
  void resetButton(void) {
    printf("Reset Button Pressed!\n");
  }

  static void resetButton(Fl_Widget* w, void*userdata) {
    GuiWindow* win = (GuiWindow*)userdata;
    win->resetButton();
  }


  // WaveformInsertButton
  void waveformInsertButton(void) {
    printf("WaveformInsert Button Pressed!\n");
  }

  static void waveformInsertButton(Fl_Widget* w, void*userdata) {
    GuiWindow* win = (GuiWindow*)userdata;
    win->waveformInsertButton();
  }

  // FsChoiceDrop
  void fsChoiceDrop(void) {
    printf("FsChoice Drop Pressed!\n");
  }

  static void fsChoiceDrop(Fl_Widget* w, void*userdata) {
    GuiWindow* win = (GuiWindow*)userdata;
    win->fsChoiceDrop();
  }


  // TChoiceDrop
  void tChoiceDrop(void) {
    printf("TChoice Drop Pressed!\n");
  }

  static void tChoiceDrop(Fl_Widget* w, void*userdata) {
    GuiWindow* win = (GuiWindow*)userdata;
    win->tChoiceDrop();
  }



public:

  ~GuiWindow ( void ) {
    delete mFsChoice;
    delete mTChoice;
    delete mPlayButton;
    delete mResetButton;
    
    delete mWaveformChoice;
    delete mWaveformFsChoice;
    delete mWaveformInsertButton;
    delete gwin;
    delete mWfm;
  } 

  GuiWindow ( int X,int Y,const char*L=0) : Fl_Window(X,Y,L) { 
        
    //add a dropdown to select sample rate
    mFsChoice = new Fl_Choice(210, h()-55, 100, 20, "Sample Rate");
    mFsChoice->add(" 100 | 1000 | 10000 ");
    mFsChoice->value(0);
    mFsChoice->callback( fsChoiceDrop, (void*)this);
    
    //add a dropdown to select sample rate
    mTChoice = new Fl_Choice(210, h()-35, 100, 20, "Duration");
    mTChoice->add(" .25 | .5 | 1 | 2 | 3 ");
    mTChoice->value(0);
    mTChoice->callback( tChoiceDrop, (void*)this);

    //make a play button
    mPlayButton = new Fl_Button(10, h()-65, 100, 20, "Play");
    mPlayButton->callback(playButton, (void*)this);
    
    //make a stop button
    mStopButton = new Fl_Button(10, h()-45, 100, 20, "Stop");
    mStopButton->callback(stopButton, (void*)this);

    // make a reset button
    mResetButton = new Fl_Button(10, h()-25, 100, 20, "Reset");
    mResetButton->callback(resetButton, (void*)this);

    // now make the drop-downs and button for the waveform insertion stuff.
    mWaveformChoice = new Fl_Choice(390, h()-45, 100, 20, "waveform");
    mWaveformChoice->add(" Sine | Triangle | Square | Random | Flat ");
    mWaveformChoice->value(0);
    
    mWaveformFsChoice = new Fl_Choice(390, h()-25, 100, 20, "at");
    mWaveformFsChoice->add(" .25 | .5 | 1 | 2 | 3 ");
    mWaveformFsChoice->value(0);
    
    mWaveformInsertButton = new Fl_Button(390, h()-65, 100, 20, "Insert");    
    mWaveformInsertButton->callback(waveformInsertButton, (void*)this);

    //put a glwindow in as part of my larger gui
    gwin = new GlWindow(10, 10, w()-20, h()-80, mWfm);

    end();
  }
};



int main(void) {
  // this creates our window
  GuiWindow win(500, 500, "Audio Playscape");
  //not sure how/why this works
  win.resizable(&win);
  //makes the window show up
  win.show();
  // This causes the fltk stuff to run until the window's closed
  return(Fl::run());
}

